home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d11 / frasrc14.arc / CALCMAND.ASM < prev    next >
Assembly Source File  |  1990-08-02  |  34KB  |  1,089 lines

  1. ;    CALCMAND.ASM - Mandelbrot/Julia Set calculation Routines
  2.  
  3. ;    The routines in this code perform Mandelbrot and Julia set
  4. ;    calculations using 32-bit integer math as opposed to the
  5. ;    "traditional" floating-point approach.
  6.  
  7. ;    This code relies on several tricks to run as quickly as it does.
  8.  
  9. ;    One can fake floating point arithmetic by using integer
  10. ;    arithmetic and keeping track of the implied decimal point
  11. ;    if things are reasonable -- and in this case, they are.
  12. ;    I replaced code that looked like: z = x*y with code that
  13. ;    looks like:
  14. ;            ix = x * ifudge         (outside the loops)
  15. ;            iy = y * ifudge
  16. ;            ....
  17. ;            iz = (ix * iy) / ifudge     (inside the loops)
  18. ;    (and keep remembering that all the integers are "ifudged" bigger)
  19.  
  20. ;    The 386 has native 32-bit integer arithmetic, and (briefly) keeps
  21. ;    64-bit values around after 32-bit multiplies.    If the result is
  22. ;    divided down right away, you've got 64-bit arithmetic.   You just
  23. ;    have to ensure that the result after the divide is <= 32 bits long.
  24. ;    CPUs predating the 386 have to emulate 32-bit arithmetic using
  25. ;    16-bit arithmetic, which is significantly slower.
  26.  
  27. ;    Dividing is slow -- but shifting is fast, and we can select our
  28. ;    "fudge factor" to be a power of two, permitting us to use that
  29. ;    method instead.   In addition, the 386 can perform 32-bit wide
  30. ;    shifting -- and even 64-bit shifts with the following logic:
  31. ;            shdr    eax,edx,cl
  32. ;            shr    edx,cl
  33. ;    so we make sure that our "fudge factor" is a power of 2 and shift
  34. ;    it down that way.
  35.  
  36.  
  37. ;                    Bert Tyler
  38.  
  39.  
  40. ;             required for compatibility if Turbo ASM
  41. IFDEF ??version
  42. MASM51
  43. QUIRKS
  44. ENDIF
  45.  
  46. .MODEL    medium,c
  47. DGROUP          group   _DATA,_DATA2
  48.  
  49. .8086
  50.  
  51.     ; these must NOT be in any segment!!
  52.     ; this get's rid of TURBO-C fixup errors
  53.  
  54.     extrn    asmdotwrite:far     ; this routine is in 'general.asm'
  55.     extrn    asmvideocleanup:far    ; this routine is in 'general.asm'
  56.     extrn    keypressed:far        ; this routine is in 'general.asm'
  57.     extrn    getakey:far        ; this routine is in 'general.asm'
  58.     extrn    iplot_orbit:far     ; this routine is in 'calcfrac.c'
  59.     extrn    scrub_orbit:far     ; this routine is in 'calcfrac.c'
  60.     extrn    intpotential:far    ; this routine is in 'calcfrac.c'
  61.  
  62.     extrn    lx0:dword, ly0:dword    ; arrays of (dword) increment values
  63.     extrn    lx1:dword, ly1:dword    ; arrays of (dword) increment values
  64.  
  65. _DATA2        segment DWORD PUBLIC 'DATA'
  66.  
  67. FUDGEFACTOR    equ    29        ; default (non-potential) fudgefactor
  68. FUDGEFACTOR2    equ    24        ; potential algoithm variant
  69.  
  70. ; ************************ External variables *****************************
  71.  
  72.     extrn    fractype:word        ; == 0 if Mandelbrot set, else Julia
  73.     extrn    numpasses:word        ; == 0 if single-pass, 1 if 2-pass
  74.     extrn    passnum:word        ; == 1 if 1st pass of 2, 2 if final pass
  75.     extrn    inside:word        ; "inside" color, normally 1 (blue)
  76.     extrn    creal:dword, cimag:dword ; Julia Set Constant
  77.     extrn    delmin:dword        ; min increment - precision required
  78.     extrn    xdots:word, ydots:word    ; number of dots across and down
  79.     extrn    maxit:word, colors:word ; maximum iterations, colors
  80.     extrn    bitshift:word        ; number of bits to shift
  81.     extrn    lm:dword        ; magnitude bailout limit
  82.     extrn    potflag:word        ; "continuous potential" flag
  83.     extrn    LogFlag:word        ; non-zero of logarithmic palettes
  84.     extrn    LogTable:dword        ; far pointer to log palette table
  85.  
  86.     extrn    ixstart:word, ixstop:word ; start, stop here
  87.     extrn    iystart:word, iystop:word ; start, stop here
  88.     extrn    yybegin:word          ; start pass 1 of 2 here
  89.     extrn    xxstart:word, xxstop:word ; window (!= ix... if symmetry)
  90.     extrn    yystart:word, yystop:word ; window (!= iy... if symmetry)
  91.     extrn    row:word, col:word      ; current pixel to calc
  92.  
  93.     extrn    calcmode:word        ; 0 if 1 or 2 pass,
  94.                     ; 1 if ssg/btm initialization call,
  95.                     ; 2 if ssg/btm 1pixel, reset periodicity
  96.                     ; 3 if ssg/btm 1pixel, no reset
  97.  
  98.     extrn    cpu:word        ; cpu type: 86, 186, 286, or 386
  99.  
  100.     extrn    andcolor:word        ; "and" value used for color selection
  101.  
  102.     extrn    show_orbit:word     ; "show-orbit" flag
  103.     extrn    orbit_ptr:word        ; "orbit pointer" flag
  104.  
  105.     extrn    symmetry:word        ; "Symmetry" flag
  106.  
  107.     extrn    debugflag:word        ; for debugging purposes only
  108.  
  109. ; ************************ Internal variables *****************************
  110.  
  111.         align    4
  112. x        dd    0        ; temp value: x
  113. y        dd    0        ; temp value: y
  114. a        dd    0        ; temp value: a
  115. b        dd    0        ; temp value: b
  116. xx        dd    0        ; temp value: x-squared
  117. yy        dd    0        ; temp value: y-squared
  118. xxmyy        dd    0        ; temp value: x-squared minus y-squared
  119. sign        db    0        ; sign calue: used by 16-bit multiplies
  120. period        db    0        ; periodicity, if in the lake
  121. color        db    0        ; the color to set a pixel
  122.         align    2
  123. temp        dw    4 dup (0)    ; temp value: used by 16-bit multiplies
  124. k        dw    0        ; local counter
  125. kbdcount    dw    0        ; keyboard counter
  126. kbdflag     dw    0        ; keyboard hit flag: 0 if no, 1 if yes
  127. oldcolor    dw    0        ; == "old" color
  128. savedand    dw    0        ; AND value for periodicity checks
  129. savedincr    dw    0        ; flag for incrementing AND value
  130.         align    4
  131. savedmask    dd    0        ; saved values mask
  132. savedx        dd    0        ; saved values of X and Y iterations
  133. savedy        dd    0        ;  (for periodicity checks)
  134.  
  135. _DATA2        ends
  136.  
  137. .CODE
  138.  
  139. ; ***************** Function calcmandasm() **********************************
  140.  
  141.     public    calcmandasm
  142.  
  143. calcmandasm proc
  144.  
  145.     push    di
  146.     push    si
  147.     push    es            ; save the original ES value
  148.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  149.     mov    es,ax            ; save it here during this routine
  150.  
  151.     mov    kbdflag,0        ; initialize keyboard int flag: nope
  152.  
  153.     cmp    calcmode,2        ; 1pixel call?
  154.     jge    short dopixel        ; yup, skip initialization, got row/col
  155.  
  156.     mov    ax,word ptr delmin    ; compute the periodicity check value
  157.     mov    dx,word ptr delmin+2    ; load smallest of delx, dely
  158.     mov    word ptr savedmask,0    ; starting value for savedmask
  159.     mov    word ptr savedmask+2,0c000h    ;  ...
  160. maskloop:
  161.     sar    word ptr savedmask+2,1    ; shift savedmask right one bit
  162.     rcr    word ptr savedmask,1    ;  ...
  163.     shl    ax,1            ; now shift delmin left one bit
  164.     rcl    dx,1            ;  ...
  165.     jnc    maskloop        ; loop if no one bits hit yet
  166.  
  167.     mov    kbdcount,100        ; init keyboard ctr high for solidguess
  168.  
  169.     cmp    calcmode,1        ; do initialization only?
  170.     jne    passstart
  171.     jmp    wedone
  172.  
  173. passstart:
  174.     mov    ax,yybegin        ; initialize outer loop
  175.     mov    row,ax            ;  ...
  176.  
  177. yloop:                    ; for (y = iystart; y <= iystop; y++)
  178.     mov    ax,ixstart        ; initialize inner loop
  179.     mov    col,ax            ;  ...
  180.  
  181. dopixel:
  182.     cmp    calcmode,3        ; 1pixel, no periodicity reset?
  183.     je    short xloop        ; inherit oldcolor from prior invocation
  184.     mov    oldcolor,0        ; set (dummy) flag: old color was high
  185.     cmp    maxit,250        ; over 250 iterations max?
  186.     jbe    short xloop        ;  nope.
  187.     mov    bx,maxit        ; yup.    reset oldcolor
  188.     sub    bx,250            ;  to maxit-250.
  189.     mov    oldcolor,bx        ;  (avoids slowness at 32000 iters)
  190.  
  191. xloop:                    ; for (x = ixstart; x <= ixstop; x++)
  192.     push    es            ; save this for a tad
  193.     mov    cx,col            ; pull lx0 value out of the array
  194.     shl    cx,1            ; convert to double-word pointer
  195.     shl    cx,1            ;  ...
  196.     les    bx,lx0
  197.     add    bx,cx
  198.     mov    ax,word ptr es:0[bx]    ;  here it is!
  199.     mov    dx,word ptr es:2[bx]    ;  ...
  200.     mov    word ptr a,ax        ; save it for later
  201.     mov    word ptr a+2,dx     ;  ...
  202.     les    bx,ly1            ; delta y per x
  203.     add    bx,cx
  204.     mov    ax,word ptr es:0[bx]    ;  here it is!
  205.     mov    dx,word ptr es:2[bx]    ;  ...
  206.     mov    word ptr b,ax        ; save it for later
  207.     mov    word ptr b+2,dx     ;  ...
  208.  
  209.     mov    cx,row            ; pull ly0 value out of the array
  210.     shl    cx,1            ; convert to double-word pointer
  211.     shl    cx,1            ;  ...
  212.     les    bx,ly0
  213.     add    bx,cx
  214.     mov    ax,word ptr es:0[bx]    ;  here it is!
  215.     mov    dx,word ptr es:2[bx]    ;  ...
  216.     add    word ptr b,ax        ; save it for later
  217.     adc    word ptr b+2,dx     ;  ...
  218.     les    bx,lx1            ; delta x per y
  219.     add    bx,cx
  220.     mov    ax,word ptr es:0[bx]    ;  here it is!
  221.     mov    dx,word ptr es:2[bx]    ;  ...
  222.     add    word ptr a,ax        ; save it for later
  223.     adc    word ptr a+2,dx     ;  ...
  224.     pop    es            ; restore the segment
  225.  
  226.     mov    ax,word ptr creal    ; initialize x == creal
  227.     mov    dx,word ptr creal+2    ;  ...
  228.     mov    word ptr x,ax        ;  ...
  229.     mov    word ptr x+2,dx     ;  ...
  230.  
  231.     mov    ax,word ptr cimag    ; initialize y == cimag
  232.     mov    dx,word ptr cimag+2    ;  ...
  233.     mov    word ptr y,ax        ;  ...
  234.     mov    word ptr y+2,dx     ;  ...
  235.  
  236.     mov    ax,maxit        ; setup k = maxit
  237.     inc    ax            ; (+ 1)
  238.     mov    k,ax            ;  (decrementing to 0 is faster)
  239.  
  240.     cmp    fractype,1        ; julia or mandelbrot set?
  241.     je    short dojulia        ; julia set - go there
  242.  
  243. ;    (Tim wants this code changed so that, for the Mandelbrot,
  244. ;    Z(1) = (x + iy) + (a + ib).  Affects only "fudged" Mandelbrots.
  245. ;    (for the "normal" case, a = b = 0, and this works, too)
  246. ;    cmp    word ptr x,0        ; Mandelbrot shortcut:
  247. ;    jne    short doeither        ;  if creal = cimag = 0,
  248. ;    cmp    word ptr x+2,0        ; the first iteration can be emulated.
  249. ;    jne    short doeither        ;  ...
  250. ;    cmp    word ptr y,0        ;  ...
  251. ;    jne    short doeither        ;  ...
  252. ;    cmp    word ptr y+2,0        ;  ...
  253. ;    jne    short doeither        ;  ...
  254. ;    dec    k            ; we know the first iteration passed
  255. ;    mov    dx,word ptr a+2     ; copy x = a
  256. ;    mov    ax,word ptr a        ;  ...
  257. ;    mov    word ptr x+2,dx     ;  ...
  258. ;    mov    word ptr x,ax        ;  ...
  259. ;    mov    dx,word ptr b+2     ; copy y = b
  260. ;    mov    ax,word ptr b        ;  ...
  261. ;    mov    word ptr y+2,dx     ;  ...
  262. ;    mov    word ptr y,ax        ;  ...
  263.  
  264.     dec    k            ; we know the first iteration passed
  265.     mov    dx,word ptr a+2     ; add x += a
  266.     mov    ax,word ptr a        ;  ...
  267.     add    word ptr x,ax        ;  ...
  268.     adc    word ptr x+2,dx     ;  ...
  269.     mov    dx,word ptr b+2     ; add y += b
  270.     mov    ax,word ptr b        ;  ...
  271.     add    word ptr y,ax        ;  ...
  272.     adc    word ptr y+2,dx     ;  ...
  273.     jmp    short doeither        ; branch around the julia switch
  274.  
  275. dojulia:                ; Julia Set initialization
  276.                     ; "fudge" Mandelbrot start-up values
  277.     mov    ax,word ptr x        ; switch x with a
  278.     mov    dx,word ptr x+2     ;  ...
  279.     mov    bx,word ptr a        ;  ...
  280.     mov    cx,word ptr a+2     ;  ...
  281.     mov    word ptr x,bx        ;  ...
  282.     mov    word ptr x+2,cx     ;  ...
  283.     mov    word ptr a,ax        ;  ...
  284.     mov    word ptr a+2,dx     ;  ...
  285.  
  286.     mov    ax,word ptr y        ; switch y with b
  287.     mov    dx,word ptr y+2     ;  ...
  288.     mov    bx,word ptr b        ;  ...
  289.     mov    cx,word ptr b+2     ;  ...
  290.     mov    word ptr y,bx        ;  ...
  291.     mov    word ptr y+2,cx     ;  ...
  292.     mov    word ptr b,ax        ;  ...
  293.     mov    word ptr b+2,dx     ;  ...
  294.  
  295. doeither:                ; common Mandelbrot, Julia set code
  296.  
  297.     cmp    numpasses,0        ; multiple-pass mode?
  298.     jz    short singlepass    ;  nope.  proceed.
  299.     cmp    passnum,2        ; second pass?
  300.     jne    short singlepass    ;  nope.  proceed
  301.     test    row,1            ; odd dot?
  302.     jnz    short singlepass    ;  yup.  proceed.
  303.     test    col,1            ; odd dot?
  304.     jnz    short singlepass    ;  yup.  proceed.
  305.     jmp    loopchecks        ;  nope. skip it.
  306. singlepass:
  307.  
  308.     mov    period,0        ; claim periodicity of 1
  309.     mov    savedand,1        ; initial periodicity check
  310.     mov    savedincr,1        ;  flag for incrementing periodicity
  311.     mov    word ptr savedx+2,0ffffh; impossible value of "old" x
  312.     mov    word ptr savedy+2,0ffffh; impossible value of "old" y
  313.     mov    orbit_ptr,0        ; clear orbits
  314.  
  315.     dec    kbdcount        ; decrement the keyboard counter
  316.     jns    short nokey        ;  skip keyboard test if still positive
  317.     mov    kbdcount,10        ; stuff in a low kbd count
  318.     cmp    show_orbit,0        ; are we showing orbits?
  319.     jne    quickkbd        ;  yup.  leave it that way.
  320.     mov    kbdcount,5000        ; else, stuff an appropriate count val
  321.     cmp    cpu,386         ; ("appropriate" to the CPU)
  322.     je    short quickkbd        ;  ...
  323.     cmp    word ptr delmin+2,1    ; is 16-bit math good enough?
  324.     ja    quickkbd        ;  yes. test less often
  325.     mov    kbdcount,500        ;  no.    test more often
  326. quickkbd:
  327.     call    far ptr keypressed    ; has a key been pressed?
  328.     cmp    ax,0            ;  ...
  329.     je    nokey            ; nope.  proceed
  330.     cmp    ax,'o'                  ; orbit toggle hit?
  331.     je    orbitkey        ;  yup.  show orbits
  332.     cmp    ax,'O'                  ; orbit toggle hit?
  333.     jne    keyhit            ;  nope.  normal key.
  334. orbitkey:
  335.     call    far ptr getakey     ; read the key for real
  336.     mov    ax,1            ; reset orbittoggle = 1 - orbittoggle
  337.     sub    ax,show_orbit        ;  ...
  338.     mov    show_orbit,ax        ;  ...
  339.     mov    kbdcount,10        ; adjust the keyboard
  340.     jmp    short nokey        ; pretend no key was hit
  341. keyhit: mov    kbdflag,-1        ; yup.    reset kbd-hit flag: yes.
  342.     jmp    wedone            ; so, bail out!
  343.  
  344. nokey:
  345.     cmp    show_orbit,0        ; is orbiting on?
  346.     jne    no16bitcode        ;  yup.  slow down.
  347.     cmp    cpu,386         ; are we on a 386?
  348.     je    short code386bit    ;  YAY!! 386-class speed!
  349.     cmp    word ptr delmin+2,1    ; OK, we're desperate.  16 bits OK?
  350.     ja    yes16bitcode        ;  YAY!  16-bit speed!
  351. no16bitcode:
  352.     call    near ptr code32bit    ; BOO!! nap time.  Full 32 bit math
  353.     jmp    kloopend        ;  bypass the 386-specific code.
  354. yes16bitcode:
  355.     call    near ptr code16bit    ; invoke the 16-bit version
  356.     jmp    kloopend        ;  bypass the 386-specific code.
  357.  
  358. .386                    ; 386-specific code starts here
  359.  
  360. code386bit:
  361.     cmp    word ptr delmin+2,3    ; is 16-bit math good enough?
  362.     jbe    code386_32        ; nope, go do 32 bit stuff
  363. IFDEF ??version
  364.     jmp    code386_32        ; TASM screws up IMUL EBX,EBX!!
  365. ENDIF
  366.  
  367.     ; 16 bit on 386, now we are really gonna move
  368.     movsx    esi,word ptr x+2    ; use SI for X
  369.     movsx    edi,word ptr y+2    ; use DI for Y
  370.     push    ebp
  371.     mov    ebp,-1
  372.     mov    cx,bitshift
  373.     dec    cx
  374.     shl    ebp,cl
  375.     sub    cx,15
  376.  
  377. kloop386_16:   ; cx=bitshift-16, ebp=overflow.mask
  378.  
  379.     mov    ebx,esi         ; compute (x * x)
  380.     imul    ebx,ebx         ;  ...
  381.     test    ebx,ebp         ; say, did we overflow? <V20-compat>
  382.     jnz    short end386_16     ;  (oops.  We done.)
  383.     shr    ebx,cl            ; get result down to 16 bits
  384.  
  385.     mov    edx,edi         ; compute (y * y)
  386.     imul    edx,edx         ;  ...
  387.     test    edx,ebp         ; say, did we overflow? <V20-compat>
  388.     jnz    short end386_16     ;  (oops.  We done.)
  389.     shr    edx,cl            ; get result down to 16 bits
  390.  
  391.     mov    ax,bx            ; compute (x*x - y*y) / fudge
  392.     sub    bx,dx            ;  for the next iteration
  393.  
  394.     add    ax,dx            ; compute (x*x + y*y) / fudge
  395.     mov    word ptr temp+6,ax    ; save last iteration value here
  396.  
  397.     cmp    ax,word ptr lm+2    ; while (xx+yy < lm)
  398.     jae    short end386_16     ;  ...
  399.  
  400.     imul    edi,esi         ; compute (y * x)
  401.     shl    edi,1            ; ( * 2 / fudge)
  402.     sar    edi,cl
  403.     add    di,word ptr b+2     ; (2*y*x) / fudge + b
  404.     movsx    edi,di            ; save as y
  405.  
  406.     add    bx,word ptr a+2     ; (from above) (x*x - y*y)/fudge + a
  407.     movsx    esi,bx            ; save as x
  408.  
  409.     mov    ax,oldcolor        ; recall the old color
  410.     cmp    ax,k            ; check it against this iter
  411.     jae    short chkpd386_16    ;  yup.  do periodicity check.
  412. nonmax386_16:
  413.     dec    k            ; while (k < maxit)
  414.     jnz    short kloop386_16    ; try, try again
  415. end386_16:
  416.     pop    ebp
  417.     jmp    kloopend        ; we done
  418.  
  419. chkpd386_16:
  420.     mov    ax,k            ; set up to test for save-time
  421.     test    ax,savedand        ; save on 0, check on anything else
  422.     jz    short chksv386_16    ;  time to save a new "old" value
  423.     mov    ax,si            ; load up x
  424.     xor    ax,word ptr savedx+2    ; does X match?
  425.     test    ax,word ptr savedmask+2 ;  truncate to appropriate precision
  426.     jne    short nonmax386_16    ;  nope.  forget it.
  427.     mov    ax,di            ; now test y
  428.     xor    ax,word ptr savedy+2    ; does Y match?
  429.     test    ax,word ptr savedmask+2 ;  truncate to appropriate precision
  430.     jne    short nonmax386_16    ;  nope.  forget it.
  431.     mov    period,1        ; note that we have found periodicity
  432.     mov    k,0            ; pretend maxit reached
  433.     jmp    short end386_16
  434. chksv386_16:
  435.     mov    word ptr savedx+2,si    ; save x
  436.     mov    word ptr savedy+2,di    ; save y
  437.     dec    savedincr        ; time to change the periodicity?
  438.     jnz    short nonmax386_16    ;  nope.
  439.     shl    savedand,1        ; well then, let's try this one!
  440.     inc    savedand        ;  (2**n -1)
  441.     mov    savedincr,4        ; and reset the increment flag
  442.     jmp    short nonmax386_16
  443.  
  444.     ; 32bit on 386:
  445. code386_32:
  446.     mov    esi,x            ; use ESI for X
  447.     mov    edi,y            ; use EDI for Y
  448.  
  449. ;    This is the main processing loop.  Here, every T-state counts...
  450.  
  451.     cmp    bitshift,29        ; only pathalogical concern for speed
  452.     jne    kloop24         ; causes us to use two algorithms here
  453.  
  454. kloop:                    ; for (k = 0; k <= maxit; k++)
  455.  
  456.     mov    eax,esi         ; compute (x * x)
  457.     imul    esi            ;  ...
  458.     shrd    eax,edx,FUDGEFACTOR    ; ( / fudge)
  459.     shr    edx,FUDGEFACTOR-1    ; (complete 64-bit shift and check
  460.     jne    short kloopend1     ; bail out if too high
  461.     mov    ebx,eax         ; save this for below
  462.  
  463.     mov    eax,edi         ; compute (y * y)
  464.     imul    edi            ;  ...
  465.     shrd    eax,edx,FUDGEFACTOR    ; ( / fudge)
  466.     shr    edx,FUDGEFACTOR-1    ; (complete 64-bit shift and check
  467.     jne    short kloopend1     ; bail out if too high
  468.  
  469.     mov    ecx,ebx         ; compute (x*x - y*y) / fudge
  470.     sub    ebx,eax         ;  for the next iteration
  471.  
  472.     add    ecx,eax         ; compute (x*x + y*y) / fudge
  473.     cmp    ecx,lm            ; while (lr < lm)
  474.     jae    short kloopend1     ;  ...
  475.  
  476.     mov    eax,edi         ; compute (y * x)
  477.     imul    esi            ;  ...
  478.     shrd    eax,edx,FUDGEFACTOR-1    ;  ( * 2 / fudge)
  479.     add    eax,b            ;  (above) + b
  480.     mov    edi,eax         ;  save this as y
  481.  
  482. ;    (from the earlier code)     ; compute (x*x - y*y) / fudge
  483.     add    ebx,a            ;    + a
  484.     mov    esi,ebx         ; save this as x
  485.  
  486.     mov    ax,oldcolor        ; recall the old color
  487.     cmp    ax,k            ; check it against this iter
  488.     jge    short chkperiod1
  489. nonmax1:
  490.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  491.     jnz    short kloop        ; while (k < maxit) ...
  492. kloopend1:
  493.     jmp    kloopend32        ; we done.
  494.  
  495. chkperiod1:
  496.     mov    eax,esi
  497.     xor    eax,savedx
  498.     test    eax,savedmask
  499.     jnz    short chksave1
  500.     mov    eax,edi
  501.     xor    eax,savedy
  502.     test    eax,savedmask
  503.     jnz    short chksave1
  504.     mov    period,1        ; note that we have found periodicity
  505.     mov    k,0            ; pretend maxit reached
  506.     jmp    short kloopend1
  507. chksave1:
  508.     mov    ax,k
  509.     test    ax,savedand
  510.     jne    short nonmax1
  511.     mov    savedx,esi
  512.     mov    savedy,edi
  513.     dec    savedincr        ; time to change the periodicity?
  514.     jnz    short nonmax1        ;  nope.
  515.     shl    savedand,1        ; well then, let's try this one!
  516.     inc    savedand        ;  (2**n -1)
  517.     mov    savedincr,4        ; and reset the increment flag
  518.     jmp    short nonmax1
  519.  
  520. kloop24:                ; for (k = 0; k <= maxit; k++)
  521.  
  522.     mov    eax,esi         ; compute (x * x)
  523.     imul    esi            ;  ...
  524.     shrd    eax,edx,FUDGEFACTOR2    ; ( / fudge)
  525.     shr    edx,FUDGEFACTOR2-1    ; (complete 64-bit shift and check
  526.     cmp    edx,0            ;  for any overflow/sign reversals)
  527.     jne    short kloopend32    ; bail out if too high
  528.     mov    ebx,eax         ; save this for below
  529.  
  530.     mov    eax,edi         ; compute (y * y)
  531.     imul    edi            ;  ...
  532.     shrd    eax,edx,FUDGEFACTOR2    ; ( / fudge)
  533.     shr    edx,FUDGEFACTOR2-1    ; (complete 64-bit shift and check
  534.     cmp    edx,0            ;  for any overflow/sign reversals)
  535.     jne    short kloopend32    ; bail out if too high
  536.  
  537.     mov    ecx,ebx         ; compute (x*x - y*y) / fudge
  538.     sub    ebx,eax         ;  for the next iteration
  539.  
  540.     add    ecx,eax         ; compute (x*x + y*y) / fudge
  541.     mov    dword ptr temp+4,ecx    ; save the last iteration value here
  542.     jo    short kloopend32    ; bail out if too high
  543.     js    short kloopend32    ;  ...
  544.     cmp    ecx,lm            ; while (lr < lm)
  545.     jae    short kloopend32    ;  ...
  546.  
  547.     mov    eax,edi         ; compute (y * x)
  548.     imul    esi            ;  ...
  549.     shrd    eax,edx,FUDGEFACTOR2-1    ;  ( * 2 / fudge)
  550.     add    eax,b            ;  (above) + b
  551.     mov    edi,eax         ;  save this as y
  552.  
  553. ;    (from the earlier code)     ; compute (x*x - y*y) / fudge
  554.     add    ebx,a            ;    + a
  555.     mov    esi,ebx         ; save this as x
  556.  
  557.     mov    ax,oldcolor        ; recall the old color
  558.     cmp    ax,k            ; check it against this iter
  559.     jb    short nonmax241     ;  nope.  bypass periodicity check.
  560.     mov    x,esi            ; save x and y
  561.     mov    y,edi            ; for the periodicity check
  562.     call    checkperiod        ; check for periodicity
  563. nonmax241:
  564.  
  565.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  566.     jnz    short kloop24        ; while (k < maxit) ...
  567.     jmp    kloopend32        ; we done.
  568.  
  569.  
  570. kloopend32:
  571.  
  572. .8086                    ; 386-specific code ends here
  573.  
  574. kloopend:
  575.     cmp    orbit_ptr,0        ; any orbits to clear?
  576.     je    noorbit2        ;  nope.
  577.     push    es            ; save es
  578.     call    far ptr scrub_orbit    ; clear out any old orbits
  579.     pop    es            ; restore es
  580. noorbit2:
  581.  
  582.     mov    ax,k            ; set old color
  583.     sub    ax,10            ; minus 10, for safety
  584.     mov    oldcolor,ax        ; and save it as the "old" color
  585.     mov    ax,maxit        ; compute color
  586.     sub    ax,k            ;  (first, re-compute "k")
  587.     sub    kbdcount,ax        ; adjust the keyboard count
  588.     cmp    ax,1            ; convert any "outlier" region
  589.     jge    short coloradjust1    ;  (where abs(x) > 2 or abs(y) > 2)
  590.     mov    ax,1            ;   to look like we ran through
  591. coloradjust1:                ;    at least one loop.
  592.     cmp    ax,maxit        ; did we max out on iterations?
  593.     jne    short coloradjust2    ;  nope.
  594.     mov    oldcolor,ax        ; set "oldcolor" to maximum
  595.     add    oldcolor,10        ;  plus a few
  596.     cmp    inside,0        ; is "inside" >= 0?
  597.     jl    coloradjust2        ;  nope.  leave it at "maxit"
  598.     mov    ax,inside        ; reset max-out color to default
  599.     cmp    debugflag,98        ; show periodicity matches?
  600.     jne    coloradjust2        ;  nope.
  601.     mov    al,period        ;  reset color to periodicity flag
  602. coloradjust2:                ;
  603.     cmp    potflag,0        ; continuous potential algorithm?
  604.     je    coloradjust3        ;  nope.  proceed.
  605.     push    es            ; prepare to call intpotential
  606.     push    ax            ; parameter #2 == the color
  607.     mov    ax,word ptr temp+6    ; parameter #1 == the overflow value
  608.     push    ax            ;  ...
  609.     mov    ax,word ptr temp+4    ;  ...
  610.     push    ax            ;  ...
  611.     call    far ptr intpotential    ; convert the color to potential
  612.     pop    es            ; restore the stack and registers
  613.     pop    es            ;  ...
  614.     pop    es            ;  ...
  615.     pop    es            ;  ...
  616. coloradjust3:                ;
  617.     cmp    LogFlag,0        ; are log palettes set?
  618.     je    coloradjust4        ;  nope.  don't use log palettes.
  619.     push    es            ; save some registers
  620.     push    si            ;  ...
  621.     les    si,LogTable        ; get the address of the Log Table
  622.     add    si,ax            ; find the offset of the color
  623.     mov    al,es:0[si]        ; replace the color value
  624.     mov    ah,0            ;  ...
  625.     pop    si            ; restore the registers
  626.     pop    es            ;  ...
  627. coloradjust4:                ;
  628.     cmp    ax,colors        ; fast skip, and avoid inside/outside=0
  629.     jl    coloradjust6        ;  no need to adjust
  630.     cmp    colors,16        ; >= 16 colors?
  631.     jge    coloradjust5        ;  branch if so
  632.     and    ax,andcolor        ; just mask the color
  633.     jmp    short coloradjust6    ; go store it
  634. coloradjust5:                          ; >=16 colors, skip using color zero
  635.     sub    dx,dx             ; setup for divide
  636.     dec    ax                ; color - 1
  637.     div     andcolor          ; divide by colors-1
  638.     mov     ax,dx             ; color-1 modulus colors-1
  639.     inc      ax               ; add back what we took off at start
  640. coloradjust6:
  641.     mov    color,al        ; color result
  642.  
  643.     mov    cx,col            ; set up the registers
  644.     mov    dx,row            ; for the write routine
  645.     call    near ptr displaydot    ; display the dot, do symmetry if any
  646.  
  647.     cmp    calcmode,0        ; called for just 1 pixel?
  648.     je    passcheck0        ;  nope, go check 1 vs 2 pass stuff
  649.     mov    al,color        ; setup return of color
  650.     xor    ah,ah            ;  ...
  651.     mov    kbdflag,ax        ;  ...
  652.     jmp    wedone            ; finished
  653.  
  654. passcheck0:
  655.     cmp    passnum,2        ; final pass?
  656.     je    loopchecks        ;  yup, no extra dots to write
  657. passcheck1:
  658.     mov    cx,col            ; set up the registers
  659.     test    cx,1            ; doing odd col at start of pass 1?
  660.     jnz    passcheck2        ;  yup, skip the dot to the right
  661.     cmp    cx,ixstop        ; at the right edge?
  662.     jge    passcheck2        ;  yup, skip the dot to the right
  663.     mov    dx,row            ; for the write routine
  664.     inc    cx            ; (but for the next x-dot)
  665.     call    near ptr displaydot    ; display the dot, do symmetry if any
  666. passcheck2:
  667.     mov    cx,col            ; set up the registers
  668.     mov    dx,row            ; for the write routine
  669.     test    dx,1            ; doing odd row at start of pass 1?
  670.     jnz    passcheck3        ;  yup, skip the row below
  671.     cmp    dx,iystop        ; at the bottom?
  672.     jge    passcheck3        ;  yup, skip the row below
  673.     inc    dx            ; (but for the next y-dot)
  674.     call    near ptr displaydot    ; display the dot, do symmetry if any
  675.     mov    cx,col            ; set up the registers
  676.     test    cx,1            ; doing odd col at start of pass 1?
  677.     jnz    loopchecks        ;  yup, skip the dot to the right
  678.     cmp    cx,ixstop        ; at the right edge?
  679.     jge    loopchecks        ;  yup, skip the dot to the right
  680.     mov    dx,row            ; for the write routine
  681.     inc    cx            ; (but for the next x-dot)
  682.     inc    dx            ; (and the next y-dot)
  683.     call    near ptr displaydot    ; display the dot, do symmetry if any
  684. passcheck3:
  685.     test    col,1            ; doing odd col at start of pass 1?
  686.     jnz    loopchecks        ;  yup, incr col just once
  687.     inc    col            ; note extra dots have been written
  688.  
  689. loopchecks:
  690.     inc    col            ; check for end of xloop
  691.     mov    ax,col            ;  ...
  692.     cmp    ax,ixstop        ;  ...
  693.     ja    loopcheck1        ; we done.
  694.     jmp    xloop            ; more to go
  695. loopcheck1:
  696.  
  697.     cmp    passnum,2        ; last pass?
  698.     je    short    lastpass    ;  yup.  proceed.
  699.     test    row,1            ; doing odd row at start of pass 1?
  700.     jnz    short    lastpass
  701.     inc    row            ; adjust y-value
  702. lastpass:
  703.  
  704.     inc    row            ; check for end of yloop
  705.     mov    ax,row            ;  ...
  706.     cmp    ax,iystop        ;  ...
  707.     ja    wedone            ; we done.
  708.     jmp    yloop            ;  nope.  more to go
  709.  
  710. wedone:                 ; restore everything and return.
  711.     call    asmvideocleanup     ; perform any video cleanup required
  712.     pop    es            ; restore the original ES value
  713.     pop    si
  714.     pop    di
  715.     mov    ax,kbdflag        ; return the keyboard-interrupt flag
  716.     ret                ; and return.
  717.  
  718. calcmandasm endp
  719.  
  720.  
  721. ; ******************** Function displaydot ******************************
  722. ;
  723. ;    Display dot, checking for out of bounds and doing symmetry.
  724. ;    Call with cx=col, dx=row.
  725. ;
  726. displaydot    proc    near
  727.  
  728.     push    cx            ; save these for symmetry plot
  729.     push    dx            ;  ...
  730.     mov    al,color        ; color to use
  731.     call    asmdotwrite        ; invoke the appropriate write-a-dot
  732.     pop    dx            ; restore row/col
  733.     pop    cx            ;  ...
  734.     cmp    symmetry,0        ; does symmetry apply?
  735.     jne    dspret            ;  nope.  done.
  736.     sub    dx,yystart        ; yystop-(row-yystart)
  737.     neg    dx            ;  ...
  738.     add    dx,yystop        ;  ...
  739.     cmp    dx,iystop        ; if not > iystop
  740.     jle    dspret            ;  this row is the axis, skip it
  741.     cmp    dx,ydots        ; out of bounds?
  742.     jge    dspret            ;  yup, skip it
  743.     cmp    fractype,0        ; Mandelbrot set?
  744.     je    dspsym            ;  yup.  Skip Julia symmetry
  745.     sub    cx,xxstart        ; convert to xxstop-(col-xxstart)
  746.     neg    cx            ;  ...
  747.     add    cx,xxstop        ;  ...
  748.     cmp    cx,xdots        ; out of bounds? (subtle possibility)
  749.     jge    dspret            ;  yup, skip it
  750. dspsym: mov    al,color        ; color to use
  751.     call    asmdotwrite        ; invoke the appropriate write-a-dot
  752. dspret: ret
  753.  
  754. displaydot    endp
  755.  
  756.  
  757. ; ******************** Function code16bit() *****************************
  758. ;
  759. ;    Performs "short-cut" 16-bit math where we can get away with it.
  760. ;
  761.  
  762. code16bit    proc    near
  763.  
  764.     mov    si,word ptr x+2     ; use SI for X
  765.     mov    di,word ptr y+2     ; use DI for Y
  766.  
  767. start16bit:
  768.     mov    ax,si            ; compute (x * x)
  769.     imul    si            ;  ...
  770.     cmp    dx,0            ; say, did we overflow? <V20-compat>
  771.     jl    end16bit        ;  (oops.  We done.)
  772.     mov    cx,32            ; ( / fudge)
  773.     sub    cx,bitshift        ;  ...
  774. loop16bit1:
  775.     shl    ax,1            ;  ...
  776.     rcl    dx,1            ;  ...
  777.     jo    end16bit        ;  (oops.  overflow)
  778.     loop    loop16bit1        ;  ...
  779.     mov    bx,dx            ; save this for a tad
  780.  
  781.     mov    ax,di            ; compute (y * y)
  782.     imul    di            ;  ...
  783.     cmp    dx,0            ; say, did we overflow? <V20-compat>
  784.     jl    end16bit        ;  (oops.  We done.)
  785.     mov    cx,32            ; ( / fudge)
  786.     sub    cx,bitshift        ;  ...
  787. loop16bit2:
  788.     shl    ax,1            ;  ...
  789.     rcl    dx,1            ;  ...
  790.     jo    end16bit        ;  (oops.  overflow)
  791.     loop    loop16bit2        ;  ...
  792.  
  793.     mov    cx,bx            ; compute (x*x - y*y) / fudge
  794.     sub    bx,dx            ;  for the next iteration
  795.  
  796.     add    cx,dx            ; compute (x*x + y*y) / fudge
  797.     mov    word ptr temp+6,cx    ; save last iteration value here
  798.     jo    end16bit        ; bail out if too high
  799.     js    end16bit        ;  ...
  800.  
  801.     cmp    cx,word ptr lm+2    ; while (xx+yy < lm)
  802.     jae    end16bit        ;  ...
  803.  
  804.     mov    ax,di            ; compute (y * x)
  805.     imul    si            ;  ...
  806.     mov    cx,33            ; ( * 2 / fudge)
  807.     sub    cx,bitshift        ;  ...
  808. loop16bit3:
  809.     shl    ax,1            ;  ...
  810.     rcl    dx,1            ;  ...
  811.     loop    loop16bit3        ;  ...
  812.     add    dx,word ptr b+2     ; (2*y*x) / fudge + b
  813.     mov    di,dx            ; save as y
  814.  
  815.     add    bx,word ptr a+2     ; (from above) (x*x - y*y)/fudge + a
  816.     mov    si,bx            ; save as x
  817.  
  818.     mov    ax,oldcolor        ; recall the old color
  819.     cmp    ax,k            ; check it against this iter
  820.     jb    short nonmax3        ;  nope.  bypass periodicity check.
  821.     mov    word ptr x+2,si     ; save x for periodicity check
  822.     mov    word ptr y+2,di     ; save y for periodicity check
  823.     call    checkperiod        ; check for periodicity
  824. nonmax3:
  825.  
  826.     dec    k            ; while (k < maxit)
  827.     jz    end16bit        ;  we done.
  828.  
  829.     jmp    start16bit        ; try, try again.
  830.  
  831. end16bit:                ; we done.
  832.     ret
  833. code16bit    endp
  834.  
  835. ; ******************** Function code32bit() *****************************
  836. ;
  837. ;    Perform the 32-bit logic required using 16-bit logic
  838.  
  839. ;    mult32bit performs 32bit x 32bit signed multiplies, with
  840. ;    (temporary) 64-bit results, and the appropriate right-shift
  841. ;    ( >> FUDGEFACTOR) before returning.   That's why it is so long.
  842. ;        arguments in SI:BX and DI:CX, results in DX:AX
  843.  
  844. mult32bit    proc near
  845.  
  846.     mov    ax,0
  847.     mov    temp+4,ax        ; first, clear out the (temporary)
  848.     mov    temp+6,ax        ;  result
  849.  
  850.     mov    sign,0            ; clear out the sign flag
  851.     cmp    si,0            ; is SI:BX negative?
  852.     jge    mults1            ;  nope
  853.     not    sign            ;  yup.  flip signs
  854.     not    bx            ;   ...
  855.     not    si            ;   ...
  856.     stc                ;   ...
  857.     adc    bx,ax            ;   ...
  858.     adc    si,ax            ;   ...
  859. mults1: cmp    di,0            ; is DI:CX negative?
  860.     jge    mults2            ;  nope
  861.     not    sign            ;  yup.  flip signs
  862.     not    cx            ;   ...
  863.     not    di            ;   ...
  864.     stc                ;   ...
  865.     adc    cx,ax            ;   ...
  866.     adc    di,ax            ;   ...
  867. mults2:
  868.  
  869.     mov    ax,bx            ; perform BX x CX
  870.     mul    cx            ;  ...
  871. ;    mov    temp,ax         ;  results in lowest 32 bits
  872.     mov    temp+2,dx        ;  ...
  873.  
  874.     mov    ax,bx            ; perform BX x DI
  875.     mul    di            ;  ...
  876.     add    temp+2,ax        ;  results in middle 32 bits
  877.     adc    temp+4,dx        ;  ...
  878.     jnc    mults3            ;  carry bit set?
  879.     inc    word ptr temp+6     ;  yup.  overflow
  880. mults3:
  881.  
  882.     mov    ax,si            ; perform SI * CX
  883.     mul    cx            ;  ...
  884.     add    temp+2,ax        ;  results in middle 32 bits
  885.     adc    temp+4,dx        ;  ...
  886.     jnc    mults4            ;  carry bit set?
  887.     inc    word ptr temp+6     ;  yup.  overflow
  888. mults4:
  889.  
  890.     mov    ax,si            ; perform SI * DI
  891.     mul    di            ;  ...
  892.     add    temp+4,ax        ; results in highest 32 bits
  893.     adc    temp+6,dx        ;  ...
  894.  
  895.     mov    ax,temp+4        ; set up to fake SHR FUDGEFACTOR
  896.     mov    dx,temp+6        ;  by SHL 3 and using high-order dword
  897.     mov    si,temp+2        ;  ...
  898.     mov    cx,32            ; ( / fudge)
  899.     sub    cx,bitshift        ;  ...
  900. multl1:
  901.     shl    si,1            ; shift one bit
  902.     rcl    ax,1            ;  ...
  903.     rcl    dx,1            ;  ...
  904.     jc    multovfl        ;  (oops.  overflow)
  905.     loop    multl1            ; shift another bit, if need be
  906.  
  907.     cmp    dx,0            ; overflow on "negative" result
  908.     jl    multovfl        ;  ...
  909.  
  910.     cmp    sign,0            ; should we negate the result?
  911.     je    mults5            ;  nope.
  912.     not    ax            ;  yup.  flip signs.
  913.     not    dx            ;   ...
  914.     mov    bx,0            ;   ...
  915.     stc                ;   ...
  916.     adc    ax,bx            ;   ...
  917.     adc    dx,bx            ;   ...
  918. mults5:
  919.  
  920. multnoovfl:                ; normal exit
  921.     clc                ;  no carry
  922.     ret                ; we done.
  923.  
  924. multovfl:                ; overflow exit
  925.     stc                ;  set carry
  926.     ret                ; we done.
  927.  
  928. mult32bit    endp
  929.  
  930. code32bit    proc near
  931.  
  932. start32bit:
  933.     mov    bx,word ptr x        ; set up to multiply x * x
  934.     mov    si,word ptr x+2     ;  ...
  935.     mov    cx,bx            ;  ...
  936.     mov    di,si            ;  ...
  937.     call    mult32bit        ; do it.
  938.     jnc    ok32bit1        ; no overflow.    continue.
  939.     jmp    end32bit        ; overflow.  we done.
  940. ok32bit1:
  941.     mov    word ptr xx,ax        ; save this for a tad.
  942.     mov    word ptr xx+2,dx    ;  ...
  943.  
  944.     mov    bx,word ptr y        ; set up to multiply y * y
  945.     mov    si,word ptr y+2     ;  ...
  946.     mov    cx,bx            ;  ...
  947.     mov    di,si            ;  ...
  948.     call    mult32bit        ; do it.
  949.     jnc    ok32bit2        ; no overflow.    continue.
  950.     jmp    end32bit        ; overflow.  we done.
  951. ok32bit2:
  952.     mov    word ptr yy,ax        ; save this for a tad.
  953.     mov    word ptr yy+2,dx    ;  ...
  954.  
  955.     mov    ax,word ptr xx        ; calculate (x*x + y*y)
  956.     mov    dx,word ptr xx+2    ;  ...
  957.     add    ax,word ptr yy        ;  ...
  958.     adc    dx,word ptr yy+2    ;  ...
  959.     jo    short end32bit        ; bail out if too high
  960.     js    short end32bit        ;  ...
  961.  
  962.     cmp    dx,word ptr lm+2    ; while (lr < lm)
  963.     jae    end32bit        ;  ...
  964.  
  965.     mov    ax,word ptr xx        ; calculate (x*x - y*y)
  966.     mov    dx,word ptr xx+2    ;  ...
  967.     sub    ax,word ptr yy        ;  ...
  968.     sbb    dx,word ptr yy+2    ;  ...
  969.     mov    word ptr xxmyy,ax    ;  ...
  970.     mov    word ptr xxmyy+2,dx    ;  ...
  971.  
  972.     mov    bx,word ptr x        ; set up to multiply x * y
  973.     mov    si,word ptr x+2     ;  ...
  974.     mov    cx,word ptr y        ;  ...
  975.     mov    di,word ptr y+2     ;  ...
  976.     call    mult32bit        ; do it.
  977.     shl    ax,1            ; multiply by 2
  978.     rcl    dx,1            ;  ...
  979.     add    ax,word ptr b        ; add b
  980.     adc    dx,word ptr b+2     ;  ...
  981.     mov    word ptr y,ax        ; save the result as y
  982.     mov    word ptr y+2,dx     ;  ...
  983.  
  984.     mov    ax,word ptr xxmyy    ; remember (x*x - y*y)
  985.     mov    dx,word ptr xxmyy+2    ;  ...
  986.     add    ax,word ptr a        ; add a
  987.     adc    dx,word ptr a+2     ;  ..
  988.     mov    word ptr x,ax        ; save the result as x
  989.     mov    word ptr x+2,dx     ;  ...
  990.  
  991.     mov    ax,oldcolor        ; recall the old color
  992.     cmp    ax,k            ; check it against this iter
  993.     jb    short nonmax2        ;  nope.  bypass periodicity check.
  994.     call    checkperiod        ; check for periodicity
  995. nonmax2:
  996.     call    checkorbit        ; check for orbiting
  997.  
  998.     dec    k            ; while (k < maxit)
  999.     jz    end32bit        ;  we done.
  1000.  
  1001.     jmp    start32bit        ; try, try again.
  1002.  
  1003. end32bit:                ; we done.
  1004.     mov    word ptr temp+6,dx    ; save last iteration value here
  1005.     ret                ;  return.
  1006. code32bit    endp
  1007.  
  1008. ;    The following routine checks for periodic loops (a known
  1009. ;    method of decay inside "Mandelbrot Lake", and an easy way to
  1010. ;    bail out of "lake" points quickly).  For speed, only the
  1011. ;    high-order sixteen bits of X and Y are checked for periodicity.
  1012. ;    For accuracy, this routine is only fired up if the previous pixel
  1013. ;    was in the lake (which means that the FIRST "wet" pixel was
  1014. ;    detected by the dull-normal maximum iteration process).
  1015.  
  1016. checkperiod    proc near        ; periodicity check
  1017.     mov    ax,k            ; set up to test for save-time
  1018.     test    ax,savedand        ; save on 0, check on anything else
  1019.     jz    checksave        ;  time to save a new "old" value
  1020.     mov    dx,word ptr x+2     ; load up x
  1021.     and    dx,word ptr savedmask+2 ;  truncate to appropriate precision
  1022.     cmp    dx,word ptr savedx+2    ; does X match?
  1023.     jne    checkdone        ;  nope.  forget it.
  1024.     mov    ax,word ptr x        ; load up x
  1025.     and    ax,word ptr savedmask    ;  truncate to appropriate precision
  1026.     cmp    ax,word ptr savedx    ; does X match?
  1027.     jne    checkdone        ;  nope.  forget it.
  1028.     mov    dx,word ptr y+2     ; now test y
  1029.     and    dx,word ptr savedmask+2 ;  truncate to appropriate precision
  1030.     cmp    dx,word ptr savedy+2    ; does Y match?
  1031.     jne    checkdone        ;  nope.  forget it.
  1032.     mov    ax,word ptr y        ; load up y
  1033.     and    ax,word ptr savedmask    ;  truncate to appropriate precision
  1034.     cmp    ax,word ptr savedy    ; does Y match?
  1035.     jne    checkdone        ;  nope.  forget it.
  1036.     mov    period,1        ; note that we have found periodicity
  1037.     mov    k,1            ; pretend maxit reached
  1038. checksave:
  1039.     mov    dx,word ptr x+2     ; load up x
  1040.     and    dx,word ptr savedmask+2 ;  truncate to appropriate precision
  1041.     mov    word ptr savedx+2,dx    ;  and save it
  1042.     mov    ax,word ptr x        ; load up x
  1043.     and    ax,word ptr savedmask    ;  truncate to appropriate precision
  1044.     mov    word ptr savedx,ax    ;  and save it
  1045.     mov    dx,word ptr y+2     ; load up y
  1046.     and    dx,word ptr savedmask+2 ;  truncate to appropriate precision
  1047.     mov    word ptr savedy+2,dx    ;  and save it
  1048.     mov    ax,word ptr y        ; load up y
  1049.     and    ax,word ptr savedmask    ;  truncate to appropriate precision
  1050.     mov    word ptr savedy,ax    ;  and save it
  1051.     dec    savedincr        ; time to change the periodicity?
  1052.     jnz    checkdone        ;  nope.
  1053.     shl    savedand,1        ; well then, let's try this one!
  1054.     inc    savedand        ;  (2**n -1)
  1055.     mov    savedincr,4        ; and reset the increment flag
  1056. checkdone:
  1057.     ret                ; we done.
  1058. checkperiod    endp
  1059.  
  1060. checkorbit    proc near
  1061.     cmp    show_orbit,0        ; was orbiting on?
  1062.     je    nonorbit1        ;  nope.
  1063.     push    es            ; save ES
  1064.     mov    ax,-1            ; push -1 onto the stack
  1065.     push    ax            ;  ...
  1066.     mov    ax,word ptr y        ; save y
  1067.     mov    dx,word ptr y+2     ;  ...
  1068.     push    dx            ;  ...
  1069.     push    ax            ;  ...
  1070.     mov    ax,word ptr x        ; save x
  1071.     mov    dx,word ptr x+2     ;  ...
  1072.     push    dx            ;  ...
  1073.     push    ax            ;  ...
  1074.     call    far ptr iplot_orbit    ; display the orbit
  1075.     pop    ax            ; clear out the parameters
  1076.     pop    ax            ;  ...
  1077.     pop    ax            ; clear out the parameters
  1078.     pop    ax            ;  ...
  1079.     pop    ax            ; clear out the parameters
  1080.     pop    es            ; restore ES
  1081. nonorbit1:
  1082.     ret
  1083. checkorbit    endp
  1084.  
  1085. calcmand_TEXT    ends
  1086.  
  1087.        end
  1088.  
  1089.